package cn.iocoder.yudao.module.system.service.tenant;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.product.TenantProductPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.product.TenantProductSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.product.TenantProductSumRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantModuleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantProductDO;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantProductMapper;
import cn.iocoder.yudao.module.system.enums.module.ModuleEnum;
import cn.iocoder.yudao.module.system.enums.product.ProductEnum;
import cn.iocoder.yudao.module.system.enums.product.ProductStatusEnum;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 外呼产品 Service 实现类
 *
 * @author 数创万维
 */
@Service
@Validated
public class TenantProductServiceImpl implements TenantProductService {

    @Resource
    private TenantProductMapper tenantProductMapper;

    @Resource
    private TenantModuleService tenantModuleService;

    @Override
    public Long createTenantProduct(TenantProductSaveReqVO createReqVO) {
        // 插入
        TenantProductDO bizProduct = BeanUtils.toBean(createReqVO, TenantProductDO.class);
        // 按照套餐来判断属于什么module， 然后给指定租户插入module -> 是否需要查询 后 更新呢？
        String code = createReqVO.getProductCode();
        TenantModuleDO tenantModuleDO = new TenantModuleDO();
        // 付费即开通
        if (ObjectUtil.equals(ProductEnum.SERVICE_ACCOUNT.getCode(), code)) {
            tenantModuleDO.setModuleCode(ModuleEnum.SERVICE.getCode());
        } else if (ObjectUtil.equals(ProductEnum.ROBOT_NUM.getCode(), code)) {
            tenantModuleDO.setModuleCode(ModuleEnum.ROBOT.getCode());
        } else if (ObjectUtil.equals(ProductEnum.AD_ACCOUNT.getCode(), code)) {
            tenantModuleDO.setModuleCode(ModuleEnum.AD.getCode());
        } else if (ObjectUtil.equals(ProductEnum.CALL_AGENT.getCode(), code)) {
            tenantModuleDO.setModuleCode(ModuleEnum.CALL.getCode());
        } else if (ObjectUtil.equals(ProductEnum.IVR_NUM.getCode(), code)) {
            tenantModuleDO.setModuleCode(ModuleEnum.CALL.getCode());
        }

        if (StrUtil.isNotEmpty(tenantModuleDO.getModuleCode())) {
            tenantModuleService.createTenantModule(tenantModuleDO);
        }
        // 返回
        tenantProductMapper.insert(bizProduct);

        return bizProduct.getId();
    }

    @Override
    public void updateTenantProduct(TenantProductDO tenantProductDO) {
        tenantProductMapper.updateById(tenantProductDO);
    }

    private void validateBizProductExists(Long id) {
        if (tenantProductMapper.selectById(id) == null) {
            throw exception(new ErrorCode(100_300_302, "产品不存在"));
        }
    }

    @Override
    public TenantProductDO getTenantProduct(Long id) {
        return tenantProductMapper.selectById(id);
    }

    @Override
    public List<TenantProductDO> getTenantProductList(Set<Long> ids) {
        return tenantProductMapper.selectList(new LambdaQueryWrapperX<TenantProductDO>().in(TenantProductDO::getId, ids));
//        return tenantProductMapper.selectList(TenantProductDO::getId, ids);
    }

    @Override
    public List<TenantProductDO> getTenantProductList() {
        return tenantProductMapper.selectList(new LambdaQueryWrapperX<TenantProductDO>().eq(TenantProductDO::getStatus, 1).orderByAsc(TenantProductDO::getId));
    }

    @Override
    public List<TenantProductDO> getExpireTenantProductList() {
        return tenantProductMapper.selectList(new LambdaQueryWrapperX<TenantProductDO>().le(TenantProductDO::getExpireAt, LocalDateTime.now()).ne(TenantProductDO::getStatus, ProductStatusEnum.EXPIRE.getStatus()));
    }

    @Override
    public PageResult<TenantProductDO> getTenantProductPage(TenantProductPageReqVO pageReqVO) {
        return tenantProductMapper.selectPage(pageReqVO);
    }

    @Override
    public Integer getRemainNumByCode(String code) {
        return tenantProductMapper.getRemainNumByCodeByTenantId(code);
    }

    @Override
    public Integer getTotalNumByCode(String code) {
        return tenantProductMapper.getTotalNumByCodeByTenantId(code);
    }

    @Override
    @TenantIgnore
    public Map<Long, List<TenantProductSumRespVO>> getRemainNumMapByTenantId(Collection<Long> ids) {
        return tenantProductMapper.getRemainNumMapByTenantId(ids).stream()
                .collect(Collectors.groupingBy(TenantProductSumRespVO::getTenantId));
    }
}